SearchBar Component
Created by: James Liu Created time: March 27, 2024 1:21 PM Tags: Frontend, UI
Overview
The SearchBar
component is a customizable search bar designed for Study Compass requiring a search functionality with autocomplete and support for abbreviations. It provides visual feedback on matching results as the user types, supports keyboard navigation, and allows users to select a result either by clicking on it or pressing the Enter key. Additionally, it incorporates an abbreviated versions feature for specific terms.
Features
- Dynamic Search Results: Updates search results in real-time as the user types, filtering based on input.
- Abbreviation Support: Can handle both full names and their corresponding abbreviations for defined terms.
- Keyboard Navigation: Allows users to navigate through the search results using the Arrow keys and to select a result with the Enter key.
- Custom Actions: Supports custom functions to be called on selecting a result or executing a search.
- Responsive Design: Adapts its appearance based on focus state and provides a clear button when input is not empty.
Props
data
: An array of strings representing all searchable items.onEnter
: A function that is called when a user selects a result or presses the Enter key. It receives the selected item as its argument.onSearch
: A function called when the Enter key is pressed without selecting a specific result. Useful for handling general search queries.room
: A string that prepopulates the search bar with an initial value, representing the current room or search term.onX
: A function called when the clear button (marked with an 'x') is clicked.
State Management
searchInput
: Controls the input value of the search bar.results
: An array of search results filtered from thedata
prop based on the user's input.isFocused
: Indicates whether the search bar is currently focused.selected
: An index marking the currently highlighted result in the dropdown list.dataAbb
: (array
) An array that includes both the full names and their corresponding abbreviations derived from thedata
prop.
Key Functions
handleInputChange
Updates the searchInput
state as the user types in the search bar.
next
Handles the action when the Enter key is pressed, either executing a search or selecting the currently highlighted result.
handleKeyDown
Manages keyboard interactions, including navigation through results and selection.
click
Handles the selection of a search result when clicked with the mouse.
handleX
Clears the current search input and executes the onX
prop function.
Key useEffect Hooks
Effect to Handle Abbreviations
useEffect(() => {
if(!data){return}
let newData = [...data];
data.map(item => {
if(removeLastWord(item) in abbreviations){
newData.push(abbreviations[removeLastWord(item)]+" "+item.split(' ').pop());
}
});
setDataAbb(newData);
}, [data]);
- Purpose: Adds support for abbreviations by creating a new data array that includes both full names and their corresponding abbreviations.
- Dependencies: Runs whenever the
data
prop changes. - Explanation: It checks each item in the
data
array, and if the item's base name matches an abbreviation, it adds the abbreviated version to the new data array (newData
). The updated array is then set to thedataAbb
state.
Effect to Filter Results Based on Search Input
useEffect(() => {
setSearchInput(searchInput.toLowerCase());
if(searchInput === "none"){
setSearchInput("");
}
if (searchInput === '' || !isFocused) {
setResults([]);
setLower("");
} else {
setSelected(0);
const filteredResults = dataAbb.filter(item =>
item.toLowerCase().startsWith(searchInput)
);
const newfilteredResults = dataAbb.filter(item => {
const includesSearchInput = item.toLowerCase().includes(searchInput.toLowerCase());
const notInResults = !results.includes(item);
return includesSearchInput && notInResults;
});
filteredResults.push(...newfilteredResults);
if (filteredResults.length === 0) {
filteredResults.push("no results found");
setLower("");
} else {
if(filteredResults.length > 1){
if(filteredResults[0].toLowerCase().startsWith(searchInput.toLowerCase())){
setLower(filteredResults[0].toLowerCase());
} else {
setLower("");
}
}
}
setResults(filteredResults);
}
}, [searchInput, dataAbb]);
- Purpose: Filters the search results based on the current
searchInput
. - Dependencies: Runs whenever the
searchInput
ordataAbb
state changes. - Explanation: Handler for the general search logic. It normalizes the
searchInput
to lowercase and checks if it's empty or if the search bar is not focused. If either condition is true, it clears the results andlower
state. Otherwise, it filtersdataAbb
based on whether items start with thesearchInput
and updates the results accordingly. It then filters dataAbb for items that include thesearchInput
but don’t start with thesearchInput
, appending those entries to the end (first display search results that start with query, then display search results that include query).
Usage
The SearchBar
component is used in Study Compass for the nameSearch, allowing users to search for classrooms by name. All classroom names are passed into the search bar. The SearchBar
component can be integrated into any application that requires a search functionality with support for keyboard navigation and abbreviation matching. It requires the parent component to provide searchable data and handle the selection of items from the search results.
Example:
<SearchBar
data={['Darrin Communications Center', 'Jonsson Engineering Center']}
onEnter={(selectedItem) => console.log('Selected:', selectedItem)}
onSearch={(query) => console.log('Search Query:', query)}
room="Darrin Communications Center"
onX={() => console.log('Search cleared')}
/>
Notes
- Ensure the
data
prop contains all searchable items - The
onEnter
andonSearch
functions must be defined to handle the selection of items and execution of search queries, respectively. - The component is designed to be flexible and easily integrated into larger applications requiring search capabilities.